package org.zeroes.common_prelude;

public class Util {

	
	public boolean isPOT(int x){
		return (x > 0 && ((x - 1) & x) == 0);
	}
	
	public boolean segments_intersect(double a1x,double a1y,double a2x,double a2y,double b1x,double b1y,double b2x,double b2y){
		if (Math.max(a1x, a2x) < Math.min(b1x, b2x)
				 || Math.min(a1x, a2x) > Math.max(b1x, b2x)
				 || Math.max(a1y, a2y) < Math.min(b1y, b2y)
				 || Math.min(a1y, a2y) > Math.max(b1y, b2y))
				{
					return false;
				}
					
		double dpx = b1x - a1x + b2x - a2x;
		double dpy = b1y - a1y + b2y - a2y;
		double qax = a2x - a1x;
		double qay = a2y - a1y;
		double qbx = b2x - b1x;
		double qby = b2y - b1y;

		double d = Math.abs(qay * qbx - qby * qax);
		double la = qbx * dpy - qby * dpx;
		double lb = qax * dpy - qay * dpx;
				
				return (Math.abs(la) <= d && Math.abs(lb) <= d);
	}
	
	public int RGB(int red, int green, int blue){
		
		return Math.max(Math.min(red, 255), 0)
				 | (Math.max(Math.min(green, 255), 0) << 8)
				 | (Math.max(Math.min(blue, 255), 0) << 16);
		
	}
	
	public int GetRValue(int rgb)
	{
		return rgb & 0xFF;
	};
	
	public int GetGValue(int rgb)
	{
		return (rgb & 0xFF00) >> 8;
	};
	
	public int GetBValue(int rgb)
	{
		return (rgb & 0xFF0000) >> 16;
	};
	
	public double clamp(double x, double a, double b){
		if (x < a)
			return a;
		else if (x > b)
			return b;
		else
			return x;
		
	}
	
	public double to_radians(double x){
		return x / (180.0 / Math.PI);
	}
	
	public double to_degrees(double x){
		return x * (180.0 / Math.PI);
	}
	public static float to_degrees(float x){
		return (float)(x * (180.0 / Math.PI));
	}
	public double clamp_angle_degrees(double a){
		
		double  angle = a;
		angle %= 360;       // now in (-360, 360) range

		if (angle < 0)
			angle += 360;   // now in [0, 360) range

		return angle;
		
	}
	
	public double clamp_angle(double a){
		double angle = a;
		angle %= 2 * Math.PI;       // now in (-2pi, 2pi) range

		if (angle < 0)
			angle += 2 * Math.PI;   // now in [0, 2pi) range

		return angle;
	}
	
	public double to_clamped_degrees(double x){
		
		return clamp_angle_degrees(to_degrees(x));
	}
	
	public double to_clamped_radians(double x){
		
		return clamp_angle(to_radians(x));
	}
	
	public double angleTo(double x1,double y1,double x2,double y2){
		double dx = x2 - x1;
        double dy = y2 - y1;
		return Math.atan2(dy, dx);
	
	}
	
	public double angleDiff(double a1, double a2){
		
		if (a1 == a2)
			return 0;

		double s1 = Math.sin(a1);
		double c1 = Math.cos(a1);
		double s2 = Math.sin(a2);
		double c2 = Math.cos(a2);
		double n = s1 * s2 + c1 * c2;
		
		// Prevent NaN results
		if (n >= 1)
			return 0;
		if (n <= -1)
			return Math.PI;
			
		return Math.acos(n);
		
	}
	
	public boolean angleClockwise(double a1, double a2){
		
		double s1 = Math.sin(a1);
		double c1 = Math.cos(a1);
		double s2 = Math.sin(a2);
		double c2 = Math.cos(a2);
		return c1 * s2 - s1 * c2 <= 0;
	}
	
	public double distanceTo(double x1, double y1,double x2, double y2){
		
		double dx = x2 - x1;
        double dy = y2 - y1;
		return Math.sqrt(dx*dx + dy*dy);
		
		
	}
	
	public  double lerp(double a , double b, double x){
		
		return a + (b - a) * x;
		
	}
	
	public double angleRotate(double start, double end, double step){
		double ss = Math.sin(start);
		double cs = Math.cos(start);
		double se = Math.sin(end);
		double ce = Math.cos(end);

		if (Math.acos(ss * se + cs * ce) > step)
		{
			if (cs * se - ss * ce > 0)
				return clamp_angle(start + step);
			else
				return clamp_angle(start - step);
		}
		else
			return clamp_angle(end);
		
	}
	
	public String fun(){
		
		return " hello from Util ";
	}
}
